home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / lpmud312.tar / lpmud312 / make_func.y < prev    next >
Text File  |  1991-12-12  |  10KB  |  435 lines

  1. %{
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include <fcntl.h>
  6. #include "lint.h"
  7. #include "config.h"
  8.  
  9. #define FUNC_SPEC     "make list_funcs"
  10. #define FUNC_TOKENS     "efun_tokens.y"
  11. #define PRE_LANG        "prelang.y"
  12. #define POST_LANG       "postlang.y"
  13. #define THE_LANG        "lang.y"
  14. #define BUFSIZ         1024
  15. #define NELEMS(arr)     (sizeof arr / sizeof arr[0])
  16.  
  17. #define MAX_FUNC      2048  /* If we need more than this we're in trouble! */
  18. int num_buff;
  19. /* For quick sort purposes : */
  20. char *key[MAX_FUNC], *buf[MAX_FUNC], has_token[MAX_FUNC];
  21.  
  22. int min_arg = -1, limit_max = 0;
  23.  
  24. /*
  25.  * arg_types is the types of all arguments. A 0 is used as a delimiter,
  26.  * marking next argument. An argument can have several types.
  27.  */
  28. int arg_types[200], last_current_type;
  29. /*
  30.  * Store the types of the current efun. They will be copied into the
  31.  * arg_types list if they were not already there (to save memory).
  32.  */
  33. int curr_arg_types[MAX_LOCAL], curr_arg_type_size;
  34.  
  35. void yyerror PROT((char *));
  36. int yylex();
  37. int yyparse();
  38. int ungetc PROT((int c, FILE *f));
  39. char *type_str PROT((int)), *etype PROT((int)), *etype1 PROT((int)),
  40.    *ctype PROT((int));
  41. #ifndef toupper
  42. int toupper PROT((int));
  43. #endif
  44.  
  45. void fatal(str)
  46.     char *str;
  47. {
  48.     fprintf(stderr, "%s", str);
  49.     exit(1);
  50. }
  51.  
  52. %}
  53. %union {
  54.     int number;
  55.     char *string;
  56. }
  57.  
  58. %token ID
  59.  
  60. %token VOID INT STRING OBJECT MIXED UNKNOWN
  61.  
  62. %token DEFAULT
  63.  
  64. %type <number> type VOID INT STRING OBJECT MIXED UNKNOWN arg_list basic typel
  65. %type <number> arg_type typel2
  66.  
  67. %type <string> ID optional_ID optional_default
  68.  
  69. %%
  70.  
  71. funcs: /* empty */ | funcs func ;
  72.  
  73. optional_ID: ID | /* empty */ { $$ = ""; } ;
  74.  
  75. optional_default: DEFAULT ':' ID { $$ = $3; } | /* empty */ { $$="0"; } ;
  76.  
  77. func: type ID optional_ID '(' arg_list optional_default ')' ';'
  78.     {
  79.     char buff[500];
  80.     char f_name[500];
  81.     int i;
  82.     if (min_arg == -1)
  83.         min_arg = $5;
  84.     if ($3[0] == '\0') {
  85.         int len;
  86.         if (strlen($2) + 1 + 2 > sizeof f_name)
  87.         fatal("A local buffer was too small!(1)\n");
  88.         sprintf(f_name, "F_%s", $2);
  89.         len = strlen(f_name);
  90.         for (i=0; i < len; i++) {
  91.         if (islower(f_name[i]))
  92.             f_name[i] = toupper(f_name[i]);
  93.         }
  94.         has_token[num_buff]=1;
  95.     } else {
  96.         if (strlen($3) + 1 > sizeof f_name)
  97.         fatal("A local buffer was too small(2)!\n");
  98.         strcpy(f_name, $3);
  99.         has_token[num_buff]=0;
  100.     }
  101.     for(i=0; i < last_current_type; i++) {
  102.         int j;
  103.         for (j = 0; j+i<last_current_type && j < curr_arg_type_size; j++)
  104.         {
  105.         if (curr_arg_types[j] != arg_types[i+j])
  106.             break;
  107.         }
  108.         if (j == curr_arg_type_size)
  109.         break;
  110.     }
  111.     if (i == last_current_type) {
  112.         int j;
  113.         for (j=0; j < curr_arg_type_size; j++) {
  114.         arg_types[last_current_type++] = curr_arg_types[j];
  115.         if (last_current_type == NELEMS(arg_types))
  116.             yyerror("Array 'arg_types' is too small");
  117.         }
  118.     }
  119.     sprintf(buff, "{\"%s\",%s,%d,%d,%s,%s,%s,%d,%s},\n",
  120.         $2, f_name, min_arg, limit_max ? -1 : $5, ctype($1),
  121.         etype(0), etype(1), i, $6);
  122.         if (strlen(buff) > sizeof buff)
  123.              fatal("Local buffer overwritten !\n");
  124.         key[num_buff] = (char *) malloc(strlen($2) + 1);
  125.     strcpy(key[num_buff], $2);
  126.     buf[num_buff] = (char *) malloc(strlen(buff) + 1);
  127.     strcpy(buf[num_buff], buff);
  128.         num_buff++;
  129.     min_arg = -1;
  130.     limit_max = 0;
  131.     curr_arg_type_size = 0;
  132.     } ;
  133.  
  134. type: basic | basic '*' { $$ = $1 | 0x10000; };
  135.  
  136. basic: VOID | INT | STRING | MIXED | UNKNOWN | OBJECT ;
  137.  
  138. arg_list: /* empty */        { $$ = 0; }
  139.     | typel2            { $$ = 1; if ($1) min_arg = 0; }
  140.     | arg_list ',' typel2     { $$ = $1 + 1; if ($3) min_arg = $$ - 1; } ;
  141.  
  142. typel2: typel
  143.     {
  144.     $$ = $1;
  145.     curr_arg_types[curr_arg_type_size++] = 0;
  146.     if (curr_arg_type_size == NELEMS(curr_arg_types))
  147.         yyerror("Too many arguments");
  148.     } ;
  149.  
  150. arg_type: type
  151.     {
  152.     if ($1 != VOID) {
  153.         curr_arg_types[curr_arg_type_size++] = $1;
  154.         if (curr_arg_type_size == NELEMS(curr_arg_types))
  155.         yyerror("Too many arguments");
  156.     }
  157.     $$ = $1;
  158.     } ;
  159.  
  160. typel: arg_type            { $$ = ($1 == VOID && min_arg == -1); }
  161.      | typel '|' arg_type     { $$ = (min_arg == -1 && ($1 || $3 == VOID));}
  162.      | '.' '.' '.'        { $$ = min_arg == -1 ; limit_max = 1; } ;
  163.  
  164. %%
  165.  
  166. struct type {
  167.     char *name;
  168.     int num;
  169. } types[] = {
  170. { "void", VOID },
  171. { "int", INT },
  172. { "string", STRING },
  173. { "object", OBJECT },
  174. { "mixed", MIXED },
  175. { "unknown", UNKNOWN }
  176. };
  177.  
  178. FILE *f;
  179. int current_line = 1;
  180.  
  181. int main(argc, argv)
  182.     int argc;
  183.     char **argv;
  184. {
  185.     int i, fdr, fdw;
  186.     char buffer[BUFSIZ + 1];
  187.  
  188.     if ((f = popen(FUNC_SPEC, "r")) == NULL) { 
  189.     perror(FUNC_SPEC);
  190.     exit(1);
  191.     }
  192.     yyparse();
  193.     /* Now sort the main_list */
  194.     for (i = 0; i < num_buff; i++) {
  195.        int j;
  196.        for (j = 0; j < i; j++)
  197.        if (strcmp(key[i], key[j]) < 0) {
  198.           char *tmp;
  199.           int tmpi;
  200.           tmp = key[i]; key[i] = key[j]; key[j] = tmp;
  201.           tmp = buf[i]; buf[i] = buf[j]; buf[j] = tmp;
  202.           tmpi = has_token[i];
  203.           has_token[i] = has_token[j]; has_token[j] = tmpi;
  204.            }
  205.     }
  206.     /* Now display it... */
  207.     printf("{\n");
  208.     for (i = 0; i < num_buff; i++)
  209.        printf("%s", buf[i]);
  210.     printf("\n};\nint efun_arg_types[] = {\n");
  211.     for (i=0; i < last_current_type; i++) {
  212.     if (arg_types[i] == 0)
  213.         printf("0,\n");
  214.     else
  215.         printf("%s,", ctype(arg_types[i]));
  216.     }
  217.     printf("};\n");
  218.     pclose(f);
  219.     /*
  220.      * Write all the tokens out.  Do this by copying the
  221.      * pre-include portion of lang.y to lang.y, appending
  222.      * this information, then appending the post-include
  223.      * portion of lang.y.  It's done this way because I don't
  224.      * know how to get YACC to #include %token files.  *grin*
  225.      */
  226.     if ((fdr = open(PRE_LANG, O_RDONLY)) < 0) {
  227.        perror(PRE_LANG);
  228.        exit(1);
  229.     }
  230.     unlink(THE_LANG);
  231.     if ((fdw = open(THE_LANG, O_CREAT | O_WRONLY, 0444)) < 0) {
  232.        perror(THE_LANG);
  233.        exit(1);
  234.     }
  235.     while (i = read(fdr, buffer, BUFSIZ))
  236.        write(fdw, buffer, i);
  237.     close(fdr);
  238.     for (i = 0; i < num_buff; i++) {
  239.        if (has_token[i]) {
  240.           char *str;   /* It's okay to mung key[*] now */
  241.           for (str = key[i]; *str; str++)
  242.             if (islower(*str)) *str = toupper(*str);
  243.           sprintf(buffer, "%%token F_%s\n", key[i]);
  244.           write(fdw, buffer, strlen(buffer));
  245.        }
  246.     }
  247.     if ((fdr = open(POST_LANG, O_RDONLY)) < 0) {
  248.        perror(POST_LANG);
  249.        exit(1);
  250.     }
  251.     while (i = read(fdr, buffer, BUFSIZ))
  252.        write(fdw, buffer, i);
  253.     close(fdr), close(fdw);
  254.     return 0;
  255. }
  256.  
  257. void yyerror(str)
  258.     char *str;
  259. {
  260.     fprintf(stderr, "%s:%d: %s\n", FUNC_SPEC, current_line, str);
  261.     exit(1);
  262. }
  263.  
  264. int ident(c)
  265.     int c;
  266. {
  267.     char buff[100];
  268.     int len, i;
  269.  
  270.     for (len=0; isalnum(c) || c == '_'; c = getc(f)) {
  271.     buff[len++] = c;
  272.     if (len + 1 >= sizeof buff)
  273.         fatal("Local buffer in ident() too small!\n");
  274.     if (len == sizeof buff - 1) {
  275.         yyerror("Too long indentifier");
  276.         break;
  277.     }
  278.     }
  279.     (void)ungetc(c, f);
  280.     buff[len] = '\0';
  281.     for (i=0; i < NELEMS(types); i++) {
  282.     if (strcmp(buff, types[i].name) == 0) {
  283.         yylval.number = types[i].num;
  284.         return types[i].num;
  285.     }
  286.     }
  287.     if (strcmp(buff, "default") == 0)
  288.     return DEFAULT;
  289.     yylval.string = malloc(strlen(buff)+1);
  290.     strcpy(yylval.string, buff);
  291.     return ID;
  292. }
  293.  
  294. char *type_str(n)
  295.     int n;
  296. {
  297.     int i, type = n & 0xffff;
  298.  
  299.     for (i=0; i < NELEMS(types); i++) {
  300.     if (types[i].num == type) {
  301.         if (n & 0x10000) {
  302.         static char buff[100];
  303.         if (strlen(types[i].name) + 3 > sizeof buff)
  304.             fatal("Local buffer too small in type_str()!\n");
  305.         sprintf(buff, "%s *", types[i].name);
  306.         return buff;
  307.         }
  308.         return types[i].name;
  309.     }
  310.     }
  311.     return "What ?";
  312. }
  313.  
  314. int yylex1() {
  315.     register int c;
  316.     
  317.     for(;;) {
  318.     switch(c = getc(f)) {
  319.     case ' ':
  320.     case '\t':
  321.         continue;
  322.     case '#':
  323.     {
  324. #ifdef sun /* no prototype in <stdio.h> *sigh* */
  325.         extern int fscanf PROT((FILE *, char *, ...));
  326. #endif
  327.         int line;
  328.         char file[2048]; /* does any operating system support
  329.                 longer pathnames? */
  330.         if ( fscanf(f,"%d \"%s\"",&line,file ) == 2 )
  331.         current_line = line;
  332.         while(c != '\n' && c != EOF)
  333.         c = getc(f);
  334.         current_line++;
  335.         continue;
  336.     }
  337.     case '\n':
  338.         current_line++;
  339.         continue;
  340.     case EOF:
  341.         return -1;
  342.     default:
  343.         if (isalpha(c))
  344.         return ident(c);
  345.         return c;
  346.     }
  347.     }
  348. }
  349.  
  350. int yylex() {
  351.     return yylex1();
  352. }
  353.  
  354. char *etype1(n)
  355.     int n;
  356. {
  357.     if (n & 0x10000)
  358.     return "T_POINTER";
  359.     switch(n) {
  360.     case INT:
  361.     return "T_NUMBER";
  362.     case OBJECT:
  363.     return "T_OBJECT";
  364.     case STRING:
  365.     return "T_STRING";
  366.     case MIXED:
  367.     return "0";    /* 0 means any type */
  368.     default:
  369.     yyerror("Illegal type for argument");
  370.     }
  371.     return "What ?";
  372. }
  373.  
  374. char *etype(n)
  375.     int n;
  376. {
  377.     int i;
  378.     int local_size = 100;
  379.     char *buff = malloc(local_size);
  380.  
  381.     for (i=0; i < curr_arg_type_size; i++) {
  382.     if (n == 0)
  383.         break;
  384.     if (curr_arg_types[i] == 0)
  385.         n--;
  386.     }
  387.     if (i == curr_arg_type_size)
  388.     return "0";
  389.     buff[0] = '\0';
  390.     for(; curr_arg_types[i] != 0; i++) {
  391.     char *p;
  392.     if (curr_arg_types[i] == VOID)
  393.         continue;
  394.     if (buff[0] != '\0')
  395.         strcat(buff, "|");
  396.     p = etype1(curr_arg_types[i]);
  397.     /*
  398.      * The number 2 below is to include the zero-byte and the next
  399.      * '|' (which may not come).
  400.      */
  401.     if (strlen(p) + strlen(buff) + 2 > local_size) {
  402.         fprintf(stderr, "Buffer overflow!\n");
  403.         exit(1);
  404.     }
  405.     strcat(buff, etype1(curr_arg_types[i]));
  406.     }
  407.     return buff;
  408. }
  409.  
  410. char *ctype(n)
  411.     int n;
  412. {
  413.     static char buff[100];    /* 100 is such a comfortable size :-) */
  414.     char *p;
  415.  
  416.     if (n & 0x10000)
  417.     strcpy(buff, "TYPE_MOD_POINTER|");
  418.     else
  419.     buff[0] = '\0';
  420.     n &= ~0x10000;
  421.     switch(n) {
  422.     case VOID: p = "TYPE_VOID"; break;
  423.     case STRING: p = "TYPE_STRING"; break;
  424.     case INT: p = "TYPE_NUMBER"; break;
  425.     case OBJECT: p = "TYPE_OBJECT"; break;
  426.     case MIXED: p = "TYPE_ANY"; break;
  427.     case UNKNOWN: p = "TYPE_UNKNOWN"; break;
  428.     default: yyerror("Bad type!");
  429.     }
  430.     strcat(buff, p);
  431.     if (strlen(buff) + 1 > sizeof buff)
  432.     fatal("Local buffer overwritten in ctype()");
  433.     return buff;
  434. }
  435.